home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / docs / ippon / ver / 050 / enemy.c < prev    next >
C/C++ Source or Header  |  2000-07-07  |  4KB  |  165 lines

  1. /* enemy.c */
  2.  
  3. #include <stdio.h>
  4. #include <xsp2lib.h>
  5.  
  6. #include "main.h"
  7. #include "player.h"
  8. #include "enemy.h"
  9. #include "shot.h"
  10.  
  11. #define ENEMY_MAX    32    /* 敵最大数 */
  12.  
  13. static ENEMY enemy[ENEMY_MAX];    /* ワーク */
  14. static ENEMY *enemy_top,    /* 使用中のワークのリスト */
  15.  *enemy_null_top,        /* 空のワークのリスト */
  16.  *enemy_end;            /* 使用中ワークのリストの末尾 */
  17.  
  18.  
  19.  
  20. /* 初期化関数へのポインタの配列 */
  21. typedef void (*enemy_alloc) (ENEMY *);
  22. enemy_alloc EnemyAllocFunc[] =
  23. {
  24.     EnemyAllocZakoA,
  25.     EnemyAllocZakoB,
  26.     EnemyAllocCoverN,
  27.     EnemyAllocOplaser,
  28. };
  29.  
  30.  
  31.  /* ゲーム開始時に呼ばれる */
  32. void EnemyInit (void)
  33. {
  34.     int i;
  35.  
  36.     /* リストをつなげる */
  37.     enemy_top = NULL;
  38.     enemy_end = NULL;
  39.     enemy_null_top = enemy;
  40.     for (i = 0; i < ENEMY_MAX; i++)
  41.         enemy[i].next = &enemy[i + 1];
  42.  
  43.     enemy[ENEMY_MAX - 1].next = NULL;
  44. }
  45.  
  46.  
  47.  
  48. /* 敵出現時に呼ばれる */
  49. ENEMY *EnemyAlloc (short type, signed short x, signed short y)
  50. {
  51.     ENEMY *p;
  52.  
  53.     if (enemy_null_top == NULL)
  54.         return (NULL);    /* 空きのワークがない(キャラクターオーバー) */
  55.  
  56.     /* リストの末尾に新しいノードを追加(他とは違うので注意) */
  57.     p = enemy_null_top;
  58.     enemy_null_top = p->next;
  59.     if (enemy_top == NULL)
  60.         enemy_top = p;
  61.     else
  62.         enemy_end->next = p;
  63.     p->next = NULL;
  64.     enemy_end = p;
  65.  
  66.     p->type = type;
  67.     p->lx = x << 16;
  68.     p->ly = y << 16;
  69.     p->shot = NULL;
  70.  
  71.     /* 関数へのポインタを使って分岐 */
  72.     /* type が 0 なら EnemyAllocA() が、1 なら EnemyAllocB() が実行される */
  73.     EnemyAllocFunc[p->type] (p);
  74.  
  75.     return (p);
  76. }
  77.  
  78.  
  79.  
  80. /* 垂直同期ごとに呼ばれる */
  81. void EnemyMove (void)
  82. {
  83.     ENEMY *p, *q;
  84.     signed short pl_x = player->x, pl_y = player->y;
  85.  
  86.     p = enemy_top;        /* 現在注目しているワーク */
  87.     q = NULL;        /* 1つ前のワーク(ワーク削除時に必要) */
  88.     while (p != NULL) {
  89.         /* 敵キャラの移動ルーチン */
  90.  
  91.         /* 関数へのポインタを使って分岐 */
  92.         /* (FuncEnemy/ 以下の FuncMoveXXX() を呼んでいる) */
  93.         if ((p->func_enemy_move) (p)) {        /* 返り値が非0なら消去 */
  94.             (p->func_enemy_free) (p);    /* 消去関数を呼ぶ */
  95.             if (q == NULL) {    /* リストの一番最初を削除 */
  96.                 enemy_top = p->next;
  97.                 p->next = enemy_null_top;
  98.                 enemy_null_top = p;
  99.                 q = NULL;
  100.                 p = enemy_top;
  101.             } else {
  102.                 if (p == enemy_end) {    /* リストの一番最後を削除 */
  103.                     q->next = NULL;
  104.                     enemy_end = q;
  105.                     p->next = enemy_null_top;
  106.                     enemy_null_top = p;
  107.                     p = q->next;
  108.                 } else {
  109.                     q->next = p->next;
  110.                     p->next = enemy_null_top;
  111.                     enemy_null_top = p;
  112.                     p = q->next;
  113.                 }
  114.             }
  115.         } else {
  116.             /* 敵キャラを消去しない場合 */
  117.             SHOT *p2 = shot;    /* 現在注目しているショットのワーク */
  118.             signed short t;
  119.  
  120.             /* プレイヤーとの当たり判定 */
  121.             if (((t = p->x + p->hit_sx) > pl_x)
  122.                 && ((t -= (short) (p->hit_sx << 1)) < pl_x)
  123.                 && ((t = p->y + p->hit_sy) > pl_y)
  124.                 && ((t -= (short) (p->hit_sy << 1)) < pl_y)) {
  125.                 /* 当たった */
  126.                 if ((player->status == PLAYER_STATUS_ALIVE) && (player->muteki == 0))
  127.                     player->status = PLAYER_STATUS_DEAD;
  128.             }
  129.             /* ショットとの当たり判定 */
  130.             if (p2->status != SHOT_STATUS_NON) {
  131.                 signed short p2_w;
  132.                 short hit_w;
  133.                 if (((t = p->x + (hit_w = p->hit_sx)) >= (p2_w = *((short *) (&p2->lx))))
  134.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  135.                     && ((t = p->y + (hit_w = p->hit_sy)) >= (p2_w = *((short *) (&p2->ly))))
  136.                     && ((t -= (short) (hit_w << 1)) <= p2_w)) {
  137.  
  138.                     p->damage++;    /* 敵キャラにダメージを与える */
  139.                     /* ショットが当たった */
  140.                     if (p->damage_mode == DAMAGE_THROUGH) {
  141.                         /* ショットが貫通する敵の場合 */
  142.                         p->shot_count = p2->shot_count;
  143.                         if (p2->shot_count < 3)
  144.                             p2->shot_count++;
  145.                     } else {
  146.                         /* ショットが刺さる敵の場合 */
  147.                         if (p2->enemy == NULL) {
  148.                             /* 既に刺さっていなければ */
  149.                             if (p2->shot_count < 3)
  150.                                 p2->shot_count++;
  151.                             p2->status = SHOT_STATUS_STICK;
  152.                             p2->enemy = p;
  153.                             p2->off_x = p2->x - p->x;
  154.                             p2->off_y = p2->y - p->y;
  155.                             p->shot = p2;
  156.                         }
  157.                     }
  158.                 }
  159.             }
  160.             q = p;
  161.             p = p->next;
  162.         }
  163.     }
  164. }
  165.